package com.runshu.newsmartark.util;

import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.runshu.newsmartark.activity.TakeStockDtaActivity;
import com.runshu.newsmartark.entity.HwInfoUtils;
import com.runshu.newsmartark.smartbox.SmartBoxHelper;
import com.runshu.newsmartark.util.common.SharedPreferencesUtils;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

import static com.runshu.newsmartark.common.ConstantUrl.Share_CustomerId;
import static com.runshu.newsmartark.common.ConstantUrl.Share_HospitalId;

/**
 * Demo class
 *
 * @author yu
 * @date 2021/10/27
 * @decs：
 */

public class MQTTManager {
    private static final String TAG = "MQTTManager";
    public static final String SERVER_HOST = "tcp://218.24.35.101:1883";
    private final String clientid = MacUtils.getFormatMacAddr();
    //用户名
    private final static String USERNAME = "rsiot";
    //密码
    private final static String PASSWORD = "rs123456";
    //发布主题
    public static String PUB_TOPIC ;
    //订阅主题
    public static String SUB_TOPIC ;
    //服务质量,0最多一次，1最少一次，2只一次
    private final static int QOS = 0;
    private static MQTTManager mqttManager = null;
    private MqttClient client;
    private MqttConnectOptions options;
    private Context mContext;


    private MessageHandlerCallBack callBack;


    private MQTTManager(Context context) {
        mContext = context;
    }

    /**
     * 获取一个MQTTManager单例
     *
     * @param context
     * @return 返回一个MQTTManager的实例对象
     */
    public static MQTTManager getInstance(Context context) {
        Log.d(TAG, "mqttManager=" + mqttManager);
        if (mqttManager == null) {
            PUB_TOPIC = "hw/" + HwInfoUtils.getCustomerId(context)   + "/" + HwInfoUtils.getHospitalId(context)   + "/" + MacUtils.getFormatMacAddr();
            SUB_TOPIC = "iot/" +HwInfoUtils.getCustomerId(context)  + "/" + HwInfoUtils.getHospitalId(context)  + "/" + MacUtils.getFormatMacAddr();
            mqttManager = new MQTTManager(context);
            synchronized (Object.class) {
                Log.d(TAG, "synchronized mqttManager=" + mqttManager);
                if (mqttManager != null) {
                    return mqttManager;
                }
            }

        } else {
            Log.d(TAG, "else mqttManager=" + mqttManager);
            return mqttManager;
        }
        return null;
    }

    /**
     * 连接服务器
     */
    public void connect() {
        Log.d(TAG, "开始连接MQtt");
        try {
            // host为主机名，clientid即连接MQTT的客户端ID，一般以唯一标识符表示，MemoryPersistence设置clientid的保存形式，默认为以内存保存
            client = new MqttClient(SERVER_HOST, clientid, new MemoryPersistence());
            // MQTT的连接设置
            options = new MqttConnectOptions();
            // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录，这里设置为true表示每次连接到服务器都以新的身份连接
            options.setCleanSession(true);
            // 设置连接的用户名
            options.setUserName(USERNAME);
            // 设置连接的密码
            options.setPassword(PASSWORD.toCharArray());
            // 设置超时时间 单位为秒
            options.setConnectionTimeout(30);
            // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线，但这个方法并没有重连的机制
//            options.setKeepAliveInterval(30);
//            options.setKeepAliveInterval(0);
            //设置断开后重新连接
            options.setAutomaticReconnect(true);
            // 设置回调
//              MqttTopic topic = client.getTopic(TOPIC);
            //setWill方法，如果项目中需要知道客户端是否掉线可以调用该方法。设置最终端口的通知消息
//              options.setWill(topic, "close".getBytes(), 2, true);
//            SSLSocketFactory sslSocketFactory = null;
               /* try {
                    sslSocketFactory = sslContextFromStream(mContext.getAssets().open("server.pem")).getSocketFactory();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                options.setSocketFactory(sslSocketFactory);*/
            client.setCallback(new PushCallback());
            //判断拦截状态，这里注意一下，如果没有这个判断，是非常坑的
            if (client.isConnected()) {
                Log.d(TAG, "client=close" );
                client.close();
//                client.disconnect();
            }
            client.connect(options);
            Log.d(TAG, "ClientId=" + clientid);
        } catch (MqttException e) {
            e.printStackTrace();
            Log.e(TAG, "connect: " + e);
        }
    }

    /**
     * 订阅消息
     *
     * @param topic 订阅消息的主题
     */
    public void subscribeMsg(String topic, int qos) {
        if (client != null) {
            int[] Qos = {qos};
            String[] topic1 = {topic};
            try {
                client.subscribe(topic1, Qos);
                Log.d(TAG, "开始订阅topic=" + topic);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 订阅消息
     *
     * @param topic 订阅消息的主题
     */
    public void unsubscribeMsg(String topic) {
        if (client != null) {
            try {
                client.unsubscribe(topic);
                Log.d(TAG, "取消订阅topic=" + topic);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 发布消息
     *
     * @param topic      发布消息主题
     * @param msg        消息体
     * @param isRetained 是否为保留消息
     */
    public void publish(String topic, String msg, boolean isRetained, int qos) {

        try {
            if (client != null) {
                MqttMessage message = new MqttMessage();
                message.setQos(qos);
                message.setRetained(isRetained);
                message.setPayload(msg.getBytes());
                client.publish(topic, message);
                Log.d(TAG, "topic=" + topic + "--msg=" + msg + "--isRetained" + isRetained);
            }
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }


    /**
     * 发布和订阅消息的回调
     */
    public class PushCallback implements MqttCallbackExtended {

        public void connectionLost(Throwable cause) {
            Log.e(TAG, "断开连接，重新连接 connectionLost: " + cause);
//            try {
//                // 断开连接
////                client.close();
//            } catch (MqttException e) {
//                e.printStackTrace();
//                Log.e(TAG, e.getMessage()+"");
//            }
//            connect();
//                new Thread(new Runnable(){
//
//                    @Override
//                    public void run() {
//                        try {
//                            Thread.sleep(3000); // 休眠3秒
//                            subscribeMsg(SUB_TOPIC, 0);
//                        } catch (InterruptedException e) {
//                            e.printStackTrace();
//                        }
//                    }
//                }).start();
//

        }

        /**
         * 发布消息的回调
         */
        @Override
        public void deliveryComplete(IMqttDeliveryToken token) {
            //publish后会执行到这里
            Log.d(TAG, "发布消息成功的回调" + token.isComplete());
        }

        /**
         * 接收消息的回调方法
         */
        @Override
        public void messageArrived(final String topicName, final MqttMessage message)
                throws Exception {
            //subscribe后得到的消息会执行到这里面
            Log.d(TAG, "接收消息==" + new String(message.getPayload()));
            if (callBack != null) {
                callBack.messageSuccess(topicName, new String(message.getPayload()));
            }
        }


        @Override
        public void connectComplete(boolean reconnect, String serverURI) {
            Log.d(TAG, "连接成功==" + reconnect);
            subscribeMsg(SUB_TOPIC, 0);
        }
    }

    /**
     * 设置接收消息的回调方法
     *
     * @param callBack
     */
    public void setMessageHandlerCallBack(MessageHandlerCallBack callBack) {
        this.callBack = callBack;
    }

    public MessageHandlerCallBack getMessageHandlerCallBack() {
        if (callBack != null) {
            return callBack;
        }
        return null;
    }


    /**
     * 断开链接
     */
    public void disconnect() {
        if (client != null && client.isConnected()) {
            try {
                client.disconnect();
                mqttManager = null;
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 释放资源
     */
    public void release() {
        if (mqttManager != null) {
            mqttManager = null;
        }
    }

    /**
     * 判断服务是否连接
     *
     * @return
     */
    public boolean isConnected() {
        if (client != null) {
            return client.isConnected();
        }
        return false;
    }


}